home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / returnadd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-11  |  8.9 KB  |  296 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: returnadd.c,v 5.8 1993/04/12 03:11:23 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.8 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: returnadd.c,v $
  17.  * Revision 5.8  1993/04/12  03:11:23  syd
  18.  * Fix to don't use address from reply-to field if it is empty.
  19.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  20.  *
  21.  * This can not happen according to RFC822. It requires at least one address if the
  22.  * reply-to is present, so this bug (EB48) isn't really a bug. But one can
  23.  * always try to be nice :-).
  24.  *
  25.  * Revision 5.7  1993/02/03  19:06:31  syd
  26.  * Remove extra strchr/strcat/strcpy et al declarations
  27.  * From: Syd
  28.  *
  29.  * Revision 5.6  1992/12/20  05:25:13  syd
  30.  * Always pass three parameters to header_cmp().
  31.  * From: chip@tct.com (Chip Salzenberg)
  32.  *
  33.  * Revision 5.5  1992/12/11  01:45:04  syd
  34.  * remove sys/types.h include, it is now included by defs.h
  35.  * and this routine includes defs.h or indirectly includes defs.h
  36.  * From: Syd
  37.  *
  38.  * Revision 5.4  1992/11/26  00:46:50  syd
  39.  * Fix how errno is used so err is inited and used instead
  40.  * as errno gets overwritten by print system call
  41.  * From: Syd
  42.  *
  43.  * Revision 5.3  1992/11/07  20:05:52  syd
  44.  * change to use header_cmp to allow for linear white space around the colon
  45.  * From: Syd
  46.  *
  47.  * Revision 5.2  1992/11/07  14:59:05  syd
  48.  * fix format variable for long
  49.  * From: Syd
  50.  *
  51.  * Revision 5.1  1992/10/03  22:58:40  syd
  52.  * Initial checkin as of 2.4 Release at PL0
  53.  *
  54.  * 
  55.  ******************************************************************************/
  56.  
  57. /** This set of routines is used to generate real return addresses
  58.     and also return addresses suitable for inclusion in a users
  59.     alias files (ie optimized based on the pathalias database).
  60.  
  61. **/
  62.  
  63. #include "headers.h"
  64. #include "s_elm.h"
  65.  
  66. #include <errno.h>
  67. #include <sys/stat.h>
  68.  
  69. char *shift_lower();
  70.  
  71. extern int errno;
  72.  
  73. char *error_description();
  74.  
  75. void
  76. get_existing_address(buffer, msgnum)
  77. char *buffer;
  78. int msgnum;
  79. {
  80.     /** This routine is called when the message being responded to has
  81.         "To:xyz" as the return address, signifying that this message is
  82.         an automatically saved copy of a message previously sent.  The
  83.         correct to address can be obtained fairly simply by reading the
  84.         To: header from the message itself and (blindly) copying it to
  85.         the given buffer.  Note that this header can be either a normal
  86.         "To:" line (Elm) or "Originally-To:" (previous versions e.g.Msg)
  87.     **/
  88.  
  89.     char mybuf[LONG_STRING];
  90.     register char ok = 1, in_to = 0;
  91.     int  err;
  92.  
  93.     buffer[0] = '\0';
  94.  
  95.     /** first off, let's get to the beginning of the message... **/
  96.  
  97.     if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  98.       dprint(1, (debugfile,
  99.         "Error: %d not a valid message number message_count = %d (%s)",
  100.         msgnum, message_count, "get_existing_address"));
  101.       error1(catgets(elm_msg_cat, ElmSet, ElmNotAValidMessageNum,
  102.         "%d not a valid message number!"), msgnum);
  103.       return;
  104.     }
  105.         if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  106.         err = errno;
  107.         dprint(1, (debugfile, 
  108.             "Error: seek %ld bytes into file hit errno %s (%s)", 
  109.             headers[msgnum]->offset, error_description(err), 
  110.             "get_existing_address"));
  111.         error2(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoFlle,
  112.            "Couldn't seek %ld bytes into file (%s)."),
  113.                headers[msgnum]->offset, error_description(err));
  114.         return;
  115.         }
  116.  
  117.         /** okay!  Now we're there!  **/
  118.  
  119.         while (ok) {
  120.           ok = (int) (mail_gets(mybuf, LONG_STRING, mailfile) != 0);
  121.       no_ret(mybuf);    /* remove return character */
  122.  
  123.           if (header_cmp(mybuf, "To", NULL) ||
  124.           header_cmp(mybuf, "Original-To", NULL)) {
  125.         in_to = TRUE;
  126.         strcpy(buffer, index(mybuf, ':') + 1);
  127.           }
  128.       else if (in_to && whitespace(mybuf[0])) {
  129.         strcat(buffer, " ");        /* tag a space in   */
  130.         strcat(buffer, (char *) mybuf + 1);    /* skip 1 whitespace */
  131.       }
  132.       else if (strlen(mybuf) < 2)
  133.         return;                /* we're done for!  */
  134.       else
  135.         in_to = 0;
  136.       }
  137. }
  138.  
  139. int
  140. get_return(buffer, msgnum)
  141. char *buffer;
  142. int msgnum;
  143. {
  144.     /** reads msgnum message again, building up the full return 
  145.         address including all machines that might have forwarded 
  146.         the message.  Returns whether it is using the To line **/
  147.  
  148.     char buf[SLEN], name1[SLEN], name2[SLEN], lastname[SLEN];
  149.     char hold_return[SLEN], alt_name2[SLEN], buf2[SLEN];
  150.     int lines, len_buf, len_buf2, colon_offset, decnet_found;
  151.     int using_to = FALSE, err;
  152.  
  153.     /* now initialize all the char buffers [thanks Keith!] */
  154.  
  155.     buf[0] = name1[0] = name2[0] = lastname[0] = '\0';
  156.     hold_return[0] = alt_name2[0] = buf2[0] = '\0';
  157.  
  158.     /** get to the first line of the message desired **/
  159.  
  160.     if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  161.       dprint(1, (debugfile,
  162.         "Error: %d not a valid message number message_count = %d (%s)",
  163.         msgnum, message_count, "get_return"));
  164.       error1(catgets(elm_msg_cat, ElmSet, ElmNotAValidMessageNum,
  165.         "%d not a valid message number!"), msgnum);
  166.       return(using_to);
  167.     }
  168.  
  169.     if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  170.       err = errno;
  171.       dprint(1, (debugfile,
  172.         "Error: seek %ld bytes into file hit errno %s (%s)", 
  173.         headers[msgnum]->offset, error_description(err), 
  174.             "get_return"));
  175.       error2(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoFlle,
  176.         "Couldn't seek %ld bytes into file (%s)."),
  177.            headers[msgnum]->offset, error_description(err));
  178.       return(using_to);
  179.     }
  180.  
  181.     /** okay!  Now we're there!  **/
  182.  
  183.     lines = headers[msgnum]->lines;
  184.  
  185.     buffer[0] = '\0';
  186.  
  187.     if (len_buf2 = mail_gets(buf2, SLEN, mailfile)) {
  188.       if(buf2[len_buf2-1] == '\n')
  189.         lines--; /* got a full line */
  190.     }
  191.  
  192.     while (len_buf2 && lines) {
  193.       buf[0] = '\0';
  194.       strncat(buf, buf2, SLEN);
  195.       len_buf = strlen(buf);
  196.       if (len_buf2 = mail_gets(buf2, SLEN, mailfile)) {
  197.         if(buf2[len_buf2-1] == '\n')
  198.           lines--; /* got a full line */
  199.       }
  200.       while (len_buf2 && lines && whitespace(buf2[0]) && len_buf >= 2) {
  201.         if (buf[len_buf-1] == '\n') {
  202.           len_buf--;
  203.           buf[len_buf] = '\0';
  204.         }
  205.         strncat(buf, buf2, (SLEN-len_buf-1));
  206.         len_buf = strlen(buf);
  207.         if (len_buf2 = mail_gets(buf2, SLEN, mailfile)) {
  208.           if(buf2[len_buf2-1] == '\n')
  209.         lines--; /* got a full line */
  210.         }
  211.       }
  212.  
  213. /* At this point, "buf" contains the unfolded header line, while "buf2" contains
  214.    the next single line of text from the mail file */
  215.  
  216.       if (first_word(buf, "From ")) 
  217.         sscanf(buf, "%*s %s", hold_return);
  218.       else if (first_word_nc(buf, ">From")) {
  219.         sscanf(buf,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s %s", 
  220.                name1, name2, alt_name2);
  221.         if (strcmp(name2, "from") == 0)        /* remote from xyz  */
  222.           strcpy(name2, alt_name2);
  223.         else if (strcmp(name2, "by") == 0)    /* forwarded by xyz */
  224.           strcpy(name2, alt_name2);
  225.         add_site(buffer, name2, lastname);
  226.       }
  227.  
  228. #ifdef USE_EMBEDDED_ADDRESSES
  229.  
  230.       else if (header_cmp(buf, "From", NULL)) {
  231.         get_address_from(buf, hold_return);
  232.         buffer[0] = '\0';
  233.           }
  234.           else if (header_cmp(buf, "Reply-To", NULL)) {
  235.         get_address_from(buf, buffer);
  236.         if (strlen(buffer) > 0) return(using_to);
  237.           }
  238.  
  239. #endif
  240.  
  241.       else if (len_buf < 2)    /* done with header */
  242.             lines = 0; /* let's get outta here!  We're done!!! */
  243.     }
  244.  
  245.     if (buffer[0] == '\0')
  246.       strcpy(buffer, hold_return); /* default address! */
  247.     else
  248.       add_site(buffer, name1, lastname);    /* get the user name too! */
  249.  
  250.     if (header_cmp(buffer, "To", NULL)) {    /* backward compatibility ho */
  251.       get_existing_address(buffer, msgnum);
  252.       using_to = TRUE;
  253.     }
  254.     else {
  255.       /*
  256.        * KLUDGE ALERT - DANGER WILL ROBINSON
  257.        * We can't just leave a bare login name as the return address,
  258.        * or it will be alias-expanded.
  259.        * So we qualify it with the current host name (and, maybe, domain).
  260.        * Sigh.
  261.        */
  262.  
  263.       if ((colon_offset = qchloc(buffer, ':')) > 0)
  264.         decnet_found = buffer[colon_offset + 1] == ':';
  265.       else
  266.         decnet_found = NO;
  267.         
  268.       if (qchloc(buffer, '@') < 0
  269.        && qchloc(buffer, '%') < 0
  270.        && qchloc(buffer, '!') < 0
  271.        && decnet_found == NO)
  272.       {
  273. #ifdef INTERNET
  274.         sprintf(buffer + strlen(buffer), "@%s", hostfullname);
  275. #else
  276.         strcpy(buf, buffer);
  277.         sprintf(buffer, "%s!%s", hostname, buf);
  278. #endif
  279.       }
  280.  
  281.       /*
  282.        * If we have a space character,
  283.        * or we DON'T have '!' or '@' chars,
  284.        * append the user-readable name.
  285.        */
  286.       if (qchloc(headers[msgnum]->from, ' ') >= 0 ||
  287.           (qchloc(headers[msgnum]->from, '!') < 0 &&
  288.            qchloc(headers[msgnum]->from, '@') < 0)) {
  289.            sprintf(buffer + strlen(buffer),
  290.                " (%s)", headers[msgnum]->from);
  291.           }
  292.     }
  293.  
  294.     return(using_to);
  295. }
  296.